﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GmepGcsMainUI.h"

#include "IComponentDto.h"
#include "IComponentLoadOperation.h"
#include "IComponentLoadBatchOperation.h"
#include "IComponentPlaceOperation.h"
#include "IComponentConsumeDataProvider.h"
#include "IComponentPlacingOptions.h"
#include "IComponentParameterDto.h"
#include "ComponentData.h"

namespace gcs
{
    class IComponentLoadOperation;
    class IComponentLoadBatchOperation;
    class IComponentPlaceOperation;
    class IGcsViewOptions;
    class IComponentConsumeDataProvider;
    class IComponentPlacingOptions;
    enum class EGcsEdition;
}
namespace gmepgcs
{

    class GCS_MAINUI_EXPORTS GmepLocalComponentOpertions :public gcs::IComponentLoadOperation ,
        public gcs::IComponentLoadBatchOperation,
        public gcs::IComponentPlaceOperation
    {
    public:

        // 单机版直接载入一个公共库构件，若本文档已经存在此同名的构件， 提示用户， 取消，跳过，还是存为副本 （1）， 取消或跳过则不载入，返回false
        // 协同版，添加一个公共库构件到项目，并下载
        virtual bool Load(gcs::EGcsEdition edition, const std::wstring &id, const std::wstring &name, const std::wstring &version, const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);

        // 单机版批量载入多个公共库构件
        // 协同版，批量添加公共库构件到项目，并下载
        virtual std::map<std::wstring, bool> LoadInBatch(gcs::EGcsEdition edition, const std::map<std::wstring, std::wstring> &idNames, const std::wstring &version, const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);

        // 单机版布置一个构件，创建实例； 若此构件没有载入，先走载入流程
        // 协同版产品库支持直接布置，先添加到项目，再下载载入布置
        virtual bool Place(gcs::EGcsEdition edition, const std::shared_ptr<gcs::IComponentDto> &spComponent, const std::shared_ptr<gcs::IComponentPlacingOptions> &spPlacingOptions, const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);

    private:
        // 单机版下载并载入公共库构件
        // pViewOptions 可以为空， 为空不需要设置进度条
        std::map<std::wstring, bool> SyncAndLoadPublicComponents(gcmp::IDocument* pDoc, const std::vector<std::tuple<std::wstring, std::wstring, std::wstring>>& idNameUniqueNameVec,
            const std::map<std::wstring, std::wstring> &idNameMap, const std::wstring & version, gcs::IGcsViewOptions *pViewOptions,
            std::map<std::wstring, std::wstring>& idCategoryCodeMap);

        // 单机版下载并载入一个公共库构件
        bool LoadOnePublicComponent(const std::wstring &id, const std::wstring &name, const std::wstring &version, gcs::IGcsViewOptions *pViewService,
            std::wstring &strUniqueName, std::wstring& strCategoryCode, bool &bSkipped);

        // 单机版批量下载并载入公共库构件
        std::map<std::wstring, bool> LoadInBatchPublicComponents(const std::map<std::wstring, std::wstring> &idNames, const std::wstring &version, const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);


        //协同版 添加公共库构件到项目，并下载
        std::map<std::wstring, bool> AddPublicComponentsToPorjectAndDownload(const std::wstring& projectId, const std::wstring& enterpriseId, const std::vector<std::wstring>& publicIdVec,
            gcs::IGcsViewOptions *pViewOptions, std::map<std::wstring, ComponentInfos>& retCompMap);

        //协同版私有化环境 添加公共库构件到项目，并下载
        std::map<std::wstring, bool> AddPublicComponentsToPorjectAndDownloadForPrivate(const std::wstring& projectId, const std::wstring& enterpriseId, 
            const std::map<std::wstring, std::wstring> &idNameMap, const std::wstring &version,
            gcs::IGcsViewOptions *pViewOptions, std::map<std::wstring, ComponentInfos>& retCompMap);

        //协同版加载一个构件
        bool LoadOneProjectComponent(const std::wstring& id, const std::wstring &name, const std::wstring &version, gcs::IGcsViewOptions *pViewOptions, std::map<std::wstring, ComponentInfos>& retCompMap, bool &bSkipped);

        //协同版批量加载构件
        std::map<std::wstring, bool> LoadInBatchProjectComponents(const std::map<std::wstring, std::wstring> &idNames, const std::wstring &version, gcs::IGcsViewOptions *pViewOptions);

        /// \brief 单机版布置操作
        bool Place4StandaloneEdition(const std::wstring &id, const std::wstring &name, const std::wstring &version, const std::wstring &familyTypeName,
            const std::vector<std::shared_ptr<gcs::IComponentParameterDto>>& instanceParams,
            const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);

        /// \brief 协同版版布置操作
        bool Place4CollaborationEdition(const std::wstring &id, const std::wstring &name, const std::wstring &version, const std::wstring &familyTypeName, 
            const std::vector<std::shared_ptr<gcs::IComponentParameterDto>>& instanceParams,
            const std::shared_ptr<gcs::IGcsViewOptions> &spViewOptions);

        /// \brief 确保项目构件已下载到本地库
        ///
        /// \param  [IN] projectId 协同项目ID
        /// \param  [IN] projectComponent 项目构件信息
        /// \param  [OUT] downloadedFamilyName 若已确保下载到本地库，则输出所记录的族名称；否则，输出空字符串
        /// \return 若已确保下载到本地库，则返回true；否则，返回false
        bool EnsureProjectComponentDownloaded(const std::wstring &projectId, const std::pair<std::wstring, ComponentInfos> &projectComponent, std::wstring &downloadedfamilyName);

        /// \brief 检查项目构件是否已载入到文档中
        ///
        /// \param  [IN] pDoc 文档指针
        /// \param  [IN] projectComponent 项目构件信息
        /// \param  [OUT] downloadedFamilyName 若已载入文档，则输出载入后的族名称；否则，输出空字符串
        /// \return 若检查到已载入到文档中，则返回true；否则，返回false
        bool CheckProjectComponentLoaded(gcmp::IDocument *pDoc, const std::pair<std::wstring, ComponentInfos> &projectComponent, std::wstring &loadedFamilyName);
    };

    class GCS_MAINUI_EXPORTS GmepLocalComponentDataProvider  : public gcs::IComponentConsumeDataProvider
    {
    public:
        virtual std::unordered_map<std::wstring, bool> CheckComponentLoaded(gcs::EGcsEdition edition, const std::vector<std::shared_ptr<gcs::IComponentDto>> &components) const;
    };

}
